package com.bright.hxj.cwduijie.manager.impl;

import com.bright.ghj.common.util.StringUtil;
import com.bright.hxj.cwduijie.constant.ConfigConstants;
import com.bright.hxj.cwduijie.converter.*;
import com.bright.hxj.cwduijie.enums.OpType;
import com.bright.hxj.cwduijie.enums.SJJHBZ;
import com.bright.hxj.cwduijie.manager.DataManager;
import com.bright.hxj.cwduijie.pojo.command.BuildCommand;
import com.bright.hxj.cwduijie.pojo.command.MonthlySettledCommand;
import com.bright.hxj.cwduijie.pojo.dto.*;
import com.bright.hxj.cwduijie.pojo.po.*;
import com.bright.hxj.cwduijie.pojo.query.DuijieQuery;
import com.bright.hxj.cwduijie.repository.*;
import com.bright.hxj.cwduijie.util.EntityManagerUtil;
import com.bright.ghj.common.util.ListUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author hxj
 * @Date 2024/7/4 16:13
 * @Description
 */

@Component
@RequiredArgsConstructor
@Slf4j
public class DataManagerImpl implements DataManager {

    private final AccSetRepository accSetRepository;
    private final AccSetConverter accSetConverter;
    private final EntityManager entityManager;
    private final ConfigConstants constants;
    private final DjFileRepository djFileRepository;


    @Override
    public Set<String> getZtDataKeyByCreditCodes(Set<String> tyshxydmSet, Integer years) {
        Set<String> dataKeySet = new HashSet<>();
        // 根据信用代码获取账套信息 一千次一次
        int count = 0;
        List<String> tyshxydmList = new ArrayList<>(tyshxydmSet);
        while (count < tyshxydmSet.size()) {
            Set<String> subList = ListUtil.getSubSet(tyshxydmList, count, count + 1000);
            // v1.8 除2024年以外 其余年份都要加在DJ_ZTXX的DATA_KEY前缀中
            List<AccSet> accSetsByTYSHXYDM;
            if (years == 2024) {
                accSetsByTYSHXYDM = accSetRepository.getAccSetsByTYSHXYDM(subList);
            } else {
                accSetsByTYSHXYDM = accSetRepository.getAccSetsByTYSHXYDM(subList, "44-" + years + "-%");
            }
            List<String> tyshxydmDataKeys = ListUtil.toSingleList(accSetsByTYSHXYDM, AccSet::getDATA_KEY);
            dataKeySet.addAll(tyshxydmDataKeys);
            count += 1000;
        }
        return dataKeySet;
    }

    @Override
    public Set<String> getCreditCodeByZtDataKeys(Set<String> ztDataKeySet) {
        Set<String> tyshxydmSet = new HashSet<>();
        // 根据ZT_DATA_KEY获取账套信息 一千次一次
        int count = 0;
        List<String> ztDataKeyList = new ArrayList<>(ztDataKeySet);
        while (count < ztDataKeySet.size()) {
            List<String> subList = ListUtil.getSubList(ztDataKeyList, count, count + 1000);
            List<AccSet> accSets = accSetRepository.getAccSetsByDATAKEYS(subList);

            List<String> tyshxydms = ListUtil.toSingleList(accSets, AccSet::getTYSHXYDM);
            tyshxydmSet.addAll(tyshxydms);
            count += 1000;
        }
        return tyshxydmSet;
    }

    @Override
    @Nullable
    public AccSetDto getAccSet(DuijieQuery duijieQuery) {
        AccSet accSet;
//        if (duijieQuery.getAccSetDataKey() != null) {
        accSet = accSetRepository.getAccSetByDATAKEY(duijieQuery.getZtDataKey());
//        } else {
//            // 如果没传指定哪个data_key 则全部账套数据进行返回
//            accSet = accSetRepository.findAll();
//        }
        return accSetConverter.poConvertDTO(accSet);
    }

    @Override
    public List<AccSet> getAllAccSetsByTYSHXYDM(DuijieQuery duijieQuery) {
        Set<String> creditCodesSet = new HashSet<>();
        if (duijieQuery.getCreditCode() != null) {
            creditCodesSet.add(duijieQuery.getCreditCode());
        } else if (duijieQuery.getCreditCodes() != null) {
            creditCodesSet.addAll(duijieQuery.getCreditCodes());
        }
        List<String> creditCodesList = new ArrayList<>(creditCodesSet);
        List<AccSet> result = new ArrayList<>();
        int count = 0;
        while (count < creditCodesSet.size()) {
            Set<String> subSet = ListUtil.getSubSet(creditCodesList, count, count + 1000);
            List<AccSet> accSetsByTYSHXYDM = accSetRepository.getAccSetsByTYSHXYDM(subSet);
            result.addAll(accSetsByTYSHXYDM);
            count+=1000;
        }
        return result;
    }

    @Override
    public AccSet getAccSetPO(DuijieQuery duijieQuery) {
        return accSetRepository.getAccSetByDATAKEY(duijieQuery.getZtDataKey());
    }

    @Override
    public List<AccSet> getAccSetsByDataKeys(DuijieQuery duijieQuery) {
        List<AccSet> accSetsByDATAKEYS = new ArrayList<>();
        List<String> ztDataKeys = duijieQuery.getZtDataKeys();
        // 进行去重
        ztDataKeys = ztDataKeys.stream().distinct().collect(Collectors.toList());
        int count = 0;
        while (count < ztDataKeys.size()) {
            List<String> subList = ListUtil.getSubList(ztDataKeys, count, count + 1000);
            List<AccSet> accSets;
            if (duijieQuery.getOpType() == null) {
                accSets = accSetRepository.getAccSetsByDATAKEYS(subList);
            } else {
                accSets = accSetRepository.getAccSetsByDATAKEYSAndOpType(subList, duijieQuery.getOpType().getValue());
            }
            accSetsByDATAKEYS.addAll(accSets);
            count += 1000;
        }
        return accSetsByDATAKEYS;
    }

    @Override
    @Transactional
    public void executeMonthlySettled(MonthlySettledCommand command) {
        Map<String, Object> params = new HashMap<>();
        params.put("zucode", command.getZtCreditCode());
        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager,
                "select acc_set as ACC_SET from " + getCwDBName() + "acc_set where zucode=:zucode", params);
        if (maps.size() > 0) {
            Object acc_set = maps.get(0).get("ACC_SET");
            String updateSQL = "exec " + getCwDBName() + "DZ_ZTYJ " + acc_set + ", " + command.getYears() + ", " + command.getMonths() + ", null";
            EntityManagerUtil.update(entityManager, updateSQL, new HashMap<>());
        } else {
            log.info("财务库acc_set表查询统一认证信用代码失败！影响月结！" + command.getZtCreditCode());
        }
    }

    @Override
    public String getCwDBName() {
        String cwdb = constants.getCwdb();
        if (StringUtil.isNotEmpty(cwdb)) {
            return cwdb + "..";
        }
        // 如果财务库名称未配置 则从中间库直接取
        return "";
    }

    @Override
    public String getZcDBName() {
        String zcdb = constants.getZcdb();
        if (StringUtil.isNotEmpty(zcdb)) {
            return zcdb + "..";
        }
        // 如果资产库名称未配置 则从中间库直接取
        return "";
    }

    @Override
    public String getDistNameByDistNo(String distNo) {
        List<Map<String, Object>> list = EntityManagerUtil.queryForMapList(entityManager, "select top 1 distName as distName from " + getZcDBName() + "dist where distNo=:distNo",
                Collections.singletonMap("distNo", distNo));
        if (list.size() == 0) return null;
        return (String) list.get(0).get("distName");
    }

    @Override
    @Transactional
    public void executeSPT(Object accSet, BuildCommand buildCommand) {
        String updateSql = "exec " + getCwDBName() + "DZ_SPT " + accSet + ", " + buildCommand.getYears() + ", " + buildCommand.getMonths() + ", null;";
        EntityManagerUtil.update(entityManager, updateSql, new HashMap<>());
    }

    @Override
    public List<String> getZtDataKeyByAccSets(List<Object> accSets) {
        Map<String, Object> params = new HashMap<>();

        int count = 0;
        List<String> allCreditCodes = new ArrayList<>();
        while (count < accSets.size()) {
            List<Object> subList = ListUtil.getSubList(accSets, count, count + 1000);

            params.put("acc_set", subList);
            List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager,
                    "select zucode as ZUCODE from " + getCwDBName() + "acc_set where acc_set in (:acc_set)", params);
            List<String> creditCodes = ListUtil.toSingleList(maps, map -> (String) map.get("ZUCODE"));
            allCreditCodes.addAll(creditCodes);
            count+= 1000;
        }
        DuijieQuery duijieQuery = new DuijieQuery();
        duijieQuery.setCreditCodes(allCreditCodes);
        List<AccSet> allAccSetsByTYSHXYDM = getAllAccSetsByTYSHXYDM(duijieQuery);
        return ListUtil.toSingleList(allAccSetsByTYSHXYDM, AccSet::getDATA_KEY);
    }


//    public String getZtDataKeyByAccSet(Object accSet) {
//        return null;
//    }


    @Override
    public List<DjFile> getNeedDuiJieFiles(DuijieQuery duijieQuery) {
        List<DjFile> allFiles = djFileRepository.getAllFiles(SJJHBZ.WAITING.getValue(), duijieQuery.getOpType().getValue(), duijieQuery.getCreditCode());
        allFiles.addAll(djFileRepository.getAllFiles(SJJHBZ.ERROR.getValue(), duijieQuery.getOpType().getValue(), duijieQuery.getCreditCode()));
        return allFiles;
    }

    @Override
    public List<Map<String, Object>> getDistsByDistNoAndLevel(String distNo, Integer level) {
        Map<String, Object> params = new HashMap<>();
        params.put("distNo", distNo + "%");
        params.put("level", level == 0 ? 6 : 9 );
        return EntityManagerUtil.queryForMapList(entityManager,
                "select distNo as distNo, distName as distName from " + getZcDBName() + "dist where distNo like :distNo and len(distNo)=:level order by distNo",
                params);
    }

    @Override
    public String getTopDistNo() {
        List<Map<String, Object>> distNos = EntityManagerUtil.queryForMapList(entityManager,
                "select top 1 distNo as distNo from " + getZcDBName() + "dist order by distNo",
                Collections.emptyMap());
        if (distNos.size() > 0) {
            return (String) distNos.get(0).get("distNo");
        }
        return "";
    }

    @Override
    public void generateContractShengNo(List<Contract> contracts) {

    }
}
